#!/usr/bin/perl

#####################################################################################
# This does not work. Idea was to run a command line to see if XML::Simple
# was installed, and if not install it. However, the "use" statement goes first, 
# and if XML::Simple is not installed the script errors right out. For now
# make sure that XML::Simple is installed by hand. In the furture might 
# wrap the real script in another script to automate this, or something.
#
#system ("perl -e 'use XML::Simple;'");
#
#if ($? > 0) {
#	print "Installing XML\n";
#	system ("perl -MCPAN -e 'install XML::Simple'");
#}
#####################################################################################


use XML::Simple;

#
# Need to feed the script a localconfig file or it won't run
#
unless (@ARGV[0]){
	die "OMG! You need to give me a localconfig file!\n";
}
$localconfigfile = @ARGV[0];

#
# Load up localconfig file
#
$localconfigobj = new XML::Simple;
$localconfig = $localconfigobj->XMLin("$localconfigfile");

#
# Get server config through wget, and load it up. Delete the file once it is loaded
#
getserverconfig();
$serverconfigobj = new XML::Simple;
$serverconfig = $serverconfigobj->XMLin("$localconfig->{serverconfig}->{repconfig}", forcearray => [ 'dep' ]);
unlink '$localconfig->{serverconfig}->{repconfig}';

#
# If a localstate config exists, load it.
#
if ( -r "$localconfig->{localconfig}->{localstate}" ) {
	$localstateobj = new XML::Simple;
	$localstate = $localstateobj->XMLin("$localconfig->{localconfig}->{localstate}", forcearray => [ 'app' ]);
	system("cp $localconfig->{localconfig}->{localstate} $localconfig->{localconfig}->{localstate}-backup");
}

#
# Dep Check - Fail if Deps Don't match up
#
@installapps = keys %{$localconfig->{localconfig}->{installapps}};
foreach $lapp (@installapps) {
	if ( ($serverconfig->{application}->{$lapp}) == 0 ) {
		die "$lapp does not exist in serverconfig! Quiting.\n";
	}
	if ( isenabled($lapp) ) {
		print "$lapp enabled, checking deps.\n";
		foreach my $dcheck ( @{$serverconfig->{application}->{$lapp}->{dep}} ) {
			print "\tChecking $dcheck.\n";
			if ( isenabled($dcheck) ) {
				print "\t$dcheck is enabled.\n";
			} else {
				die "$dcheck is not enabled. Dep check failed.\n\n";
			}
		}
	}
}

print "All deps are in order - Starting installation!\n\n\n";

#
# Install the various apps
#
$work_app = pop(@installapps);
while ($work_app) {
	if ($localconfig->{localconfig}->{installapps}->{$work_app}) {
		installapp($work_app);
	}

# Move on to the next app	
	$work_app = pop(@installapps);
}

print "Output from install scripts saved in installoutput.txt.\n";
print "Done!\n\n";

#####################################################################################
# Start Subs
#####################################################################################

# Wrapper for installing apps
# Calls checklocalstate -> deps -> installscript -> updatelocalstate
sub installapp {
	my $doapp = $_[0];
	print "Working on $doapp!\n";
	if (checklocalstate()) {
		print "$doapp allready installed.\n";
		return 1;
	}
#	print "about deps\n";
	if ( deps($doapp) ) {
		print "Dep install failed. Can not install $doapp.\n";
		return 1;
	}
	if ( installscript($doapp) ) {
		print "$doapp failed install!\n";
		return 1;
	}
	$localstate->{app}->{$doapp}->{internalversion} = $serverconfig->{application}->{$doapp}->{internalversion};
	print "$doapp installed correctly!\n";
	updatelocalstate();
	return 0;
}	

sub deps {
	my $doapp = $_[0];
	print "Checking deps of $doapp\n";

	foreach my $dcheck ( @{$serverconfig->{application}->{$doapp}->{dep}} ) {
			print "\tChecking $dcheck.\n";
			unless ( checklocalstate($dcheck) ) {
				print "\t$dcheck is installed.\n";
			} else {
				print "\t$dcheck is not installed.\n";
				if ( installapp($dcheck) ) {
					print "Dep install of $dcheck failed.\n";
					return 1;
				}
			}
		}
	
	return 0;
}

sub installscript {
	my $doapp = $_[0];
	print "Installing $doapp\n";
	@servervars = keys %{$serverconfig->{serverconfig}};
	foreach my $wvar (@servervars) {
		$ENV{"$wvar"} = "$serverconfig->{serverconfig}->{$wvar}";
	}
	@appvars = keys %{$serverconfig->{application}->{$doapp}};
	foreach my $wvar (@appvars) {
		$ENV{"$wvar"} = "$serverconfig->{application}->{$doapp}->{$wvar}";
	}
	system ("wget -q -P $serverconfig->{serverconfig}->{builddir} $localconfig->{serverconfig}->{repbase}$localconfig->{serverconfig}->{appconfigbase}$serverconfig->{application}->{$doapp}->{installscript}");
	system ("chmod +x $serverconfig->{serverconfig}->{builddir}/$serverconfig->{application}->{$doapp}->{installscript}");
	
	if ( system ("$serverconfig->{serverconfig}->{builddir}/$serverconfig->{application}->{$doapp}->{installscript} >> installoutput.txt 2>&1") ) {
		print "$doapp did not install! Exiting!\n";
		unlink "$serverconfig->{serverconfig}->{builddir}/$serverconfig->{application}->{$doapp}->{installscript}";
		return 1;
	}
	unlink "$serverconfig->{serverconfig}->{builddir}/$serverconfig->{application}->{$doapp}->{installscript}";
	return 0;
}

sub checklocalstate {
# Returns 1 if app has been installed
# Returns 0 if app has not been installed
	unless ( $localstate->{app}->{$work_app}->{internalversion} ) {
			return 0;
	}
	if ( $localstate->{app}->{$work_app}->{internalversion} >= $serverconfig->{application}->{$work_app}->{internalversion} ) {
#		print "check return 1\n";
		return 1;
	} else {
#		print "check return 0\n";
		return 0;
	}
}

# Sub to get server config file with wget
sub getserverconfig {
	print "Getting server config\n\n\n";
	print "$localconfig->{serverconfig}->{repbase}$localconfig->{serverconfig}->{appconfigbase}$localconfig->{serverconfig}->{repconfig}\n";
	system ("wget -q $localconfig->{serverconfig}->{repbase}$localconfig->{serverconfig}->{appconfigbase}$localconfig->{serverconfig}->{repconfig}");
}

# Write out Localstate updates
sub updatelocalstate {
	open (LOCALSTATE, "> $localconfig->{localconfig}->{localstate}");
	$localstateoutput = XML::Simple->new();
	print LOCALSTATE $localstateoutput->XMLout($localstate,RootName=>'installed',noattr=>1,xmldecl=>'<?xml version="1.0" encoding="UTF-8"?>');
	close (LOCALSTATE);
}

sub isenabled {
	my $checkapp = $_[0];
	if ( $localconfig->{localconfig}->{installapps}->{$checkapp} == "1" ) {
		return 1;
	} else {
		return 0;
	}
}
